package per.hx.bs.web.sys.controller;

import com.alibaba.fastjson.JSON;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import per.hx.bs.base.BaseController;
import per.hx.bs.base.annotation.BsCLog;
import per.hx.bs.base.domain.PageDTO;
import per.hx.bs.base.domain.ReturnDTO;
import per.hx.bs.base.entity.EmailVO;
import per.hx.bs.constant.DictTpye;
import per.hx.bs.constant.Setting;
import per.hx.bs.entity.sys.SysDictDO;
import per.hx.bs.entity.sys.SysNotifyDO;
import per.hx.bs.entity.sys.SysNotifyRecordDO;
import per.hx.bs.entity.sys.SysUserDO;
import per.hx.bs.util.PageUtils;
import per.hx.bs.web.other.service.EmailService;
import per.hx.bs.web.sys.service.SysDictService;
import per.hx.bs.web.sys.service.SysNotifyRecordService;
import per.hx.bs.web.sys.service.SysNotifyService;
import per.hx.bs.web.sys.service.SysUserService;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author HuXing
 * @date 2018/3/30  16:12
 */
@Controller
@RequestMapping("sys/notify")
public class NotifyController extends BaseController {


    private final String prefix = "system/notify/";

    private final static Pattern PATTERN = Pattern.compile("^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\\.([a-zA-Z0-9_-])+)+$");

    private final
    SysNotifyService sysNotifyService;
    private final
    SysNotifyRecordService sysNotifyRecordService;
    private final
    SysDictService sysDictService;
    private final
    EmailService emailService;

    private final
    SysUserService userService;

    @Autowired
    public NotifyController(SysNotifyService sysNotifyService, SysNotifyRecordService sysNotifyRecordService, SysDictService sysDictService, EmailService emailService, SysUserService userService) {
        this.sysNotifyService = sysNotifyService;
        this.sysNotifyRecordService = sysNotifyRecordService;
        this.sysDictService = sysDictService;
        this.emailService = emailService;
        this.userService = userService;
    }


    @BsCLog("进入通知管理界面")
    @RequiresPermissions("sys:notify:notify")
    @GetMapping(value = {"/", ""})
    public String oaNotify() {
        return prefix + "notify";
    }

    @BsCLog("获取通知管理界面")
    @RequiresPermissions("sys:notify:notify")
    @GetMapping(value = "/list")
    @ResponseBody
    public PageUtils list(@RequestParam Map<String, Object> params) {
        List<SysNotifyDO> notifyList = sysNotifyService.list(params);
        int total = sysNotifyService.count(params);
        return new PageUtils(notifyList, total);
    }

    @BsCLog("获取通知管理界面")
    @RequiresPermissions("sys:notify:add")
    @GetMapping(value = "/add")
    public String add() {
        return prefix + "add";
    }

    @BsCLog("进入通知修改界面")
    @RequiresPermissions("sys:notify:edit")
    @GetMapping(value = "/edit/{id}")
    public String edit(@PathVariable("id") Long id, Model model) {
        SysNotifyDO notify = sysNotifyService.get(id);
        List<SysDictDO> sysDictDOS = sysDictService.listByType(DictTpye.SYS_NOTIFY_TYPE);
        String type = notify.getType();
        for (SysDictDO sysDictDO : sysDictDOS) {
            if (type.equals(sysDictDO.getName())) {
                sysDictDO.setRemark("selected");
            } else {
                sysDictDO.setRemark(null);
            }
        }
        if (Setting.SYS_NOTIFY_STATUS.equals(notify.getStatus())) {
            notify.setStatus("true");
        } else {
            notify.setStatus("false");
        }
        if (Setting.SYS_NOTIFY_EMAIL.equals(notify.getSendEmail())) {
            notify.setSendEmail("true");
        } else {
            notify.setSendEmail("false");
        }
        model.addAttribute("sysNotifyTypes", sysDictDOS);
        model.addAttribute("notify", notify);
        return prefix + "edit";
    }

    @BsCLog("保存通知")
    @RequiresPermissions("sys:notify:add")
    @PostMapping(value = "/save")
    @ResponseBody
    public ReturnDTO save(SysNotifyDO sysNotifyDO) {
        try {
            sysNotifyDO.setCreateId(getUserId());
            sysNotifyService.save(sysNotifyDO);
        } catch (RuntimeException r) {
            return ReturnDTO.error(r.getMessage());
        }
        String status = sysNotifyDO.getStatus();
        String sendEmail = sysNotifyDO.getSendEmail();
        Long[] userIds = sysNotifyDO.getUserIds();

        try {
            return ReturnDTO.ok(sendEmail(sysNotifyDO, status, sendEmail, userIds));
        } catch (Exception e) {
            return ReturnDTO.error("邮件发送失败");
        }
    }

    @BsCLog("更新通知")
    @RequiresPermissions("sys:notify:edit")
    @PostMapping(value = "/update")
    @ResponseBody
    public ReturnDTO update(SysNotifyDO sysNotifyDO) {
        if ("".equals(sysNotifyDO.getStatus()) || sysNotifyDO.getStatus() == null) {
            sysNotifyDO.setStatus("0");
        }
        if ("".equals(sysNotifyDO.getSendEmail()) || sysNotifyDO.getSendEmail() == null) {
            sysNotifyDO.setSendEmail("0");
        }
        if (sysNotifyService.update(sysNotifyDO) == 0) {
            return ReturnDTO.error();
        }
        String status = sysNotifyDO.getStatus();
        String sendEmail = sysNotifyDO.getSendEmail();
        Long[] userIds = null;

        Map<String, Object> map = new HashMap<String, Object>(1);
        map.put("notifyId", sysNotifyDO.getId());
        List<SysNotifyRecordDO> recordDOS = sysNotifyRecordService.list(map);
        if (!recordDOS.isEmpty()) {
            List<Long> ids = new ArrayList<Long>(recordDOS.size());
            for (SysNotifyRecordDO recordDO : recordDOS) {
                ids.add(recordDO.getUserId());
            }
            userIds = new Long[ids.size()];
            ids.toArray(userIds);
        }
        try {
            return ReturnDTO.ok(sendEmail(sysNotifyDO, status, sendEmail, userIds));
        } catch (Exception e) {
            return ReturnDTO.error("邮件发送失败");
        }
    }

    private String sendEmail(SysNotifyDO sysNotifyDO, String status, String sendEmail, Long[] userIds) {
        String str = "1";
        if (null != userIds && userIds.length > 0 && str.equals(status) && str.equals(sendEmail)) {
            List<SysUserDO> userDOS = userService.selectByIds(userIds);
            if (null != userDOS && !userDOS.isEmpty()) {
                List<String> list = new ArrayList<String>();
                for (SysUserDO userDO : userDOS) {
                    Matcher m = PATTERN.matcher(userDO.getEmail());
                    if (m.matches()) {
                        list.add(userDO.getEmail());
                    }
                }
                try {
                    if (!list.isEmpty()) {
                        EmailVO emailVO = new EmailVO();
                        String[] emails = new String[list.size()];
                        list.toArray(emails);
                        emailVO.setEmail(emails);
                        emailVO.setSubject(sysNotifyDO.getTitle());
                        emailVO.setContent(sysNotifyDO.getContent());
                        emailService.sendEmail(emailVO);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                }
            }
        }
        return "邮件发送成功";
    }

    @BsCLog("删除通知")
    @RequiresPermissions("sys:notify:remove")
    @PostMapping(value = "/remove")
    @ResponseBody
    public ReturnDTO remove(Long id) {
        if (sysNotifyService.remove(id) > 0) {
            return ReturnDTO.ok();
        }
        return ReturnDTO.error();
    }

    @BsCLog("删除通知")
    @RequiresPermissions("sys:notify:remove")
    @PostMapping(value = "/removeRecord")
    @ResponseBody
    public ReturnDTO removeRecord(Long id) {
        if (sysNotifyRecordService.remove(id, getUserId()) > 0) {
            return ReturnDTO.ok();
        }
        return ReturnDTO.error();
    }

    @BsCLog("批量删除通知")
    @RequiresPermissions("sys:notify:remove")
    @PostMapping(value = "/batchRemove")
    @ResponseBody
    public ReturnDTO remove(@RequestParam("ids[]") Long[] ids) {

        if (sysNotifyService.batchRemove(ids) > 0) {
            return ReturnDTO.ok();
        } else {
            return ReturnDTO.error();
        }
    }

    @BsCLog("批量标记为已读通知")
    @PostMapping(value = "/batchRead")
    @ResponseBody
    public ReturnDTO batchRead(@RequestParam("ids[]") Long[] ids) {
        if (sysNotifyRecordService.batchRead(ids, getUserId()) > 0) {
            return ReturnDTO.ok();
        } else {
            return ReturnDTO.error();
        }
    }

    @BsCLog("批量标记为已读通知")
    @PostMapping(value = "/batchRemoveRecord")
    @ResponseBody
    public ReturnDTO batchRemoveRecord(@RequestParam("ids[]") Long[] ids) {
        if (sysNotifyRecordService.batchRemoveRecord(ids, getUserId()) > 0) {
            return ReturnDTO.ok();
        } else {
            return ReturnDTO.error();
        }
    }

    @BsCLog("通知详情")
    @RequiresPermissions("sys:notify:notify")
    @GetMapping(value = "/message")
    @ResponseBody
    public PageDTO message() {
        Map<String, Object> params = new HashMap<String, Object>(4);
        params.put("offset", 0);
        params.put("limit", 3);
        params.put("userId", getUserId());
        params.put("isRead", Setting.SYS_NOTIFY_READ_NO);
        return JSON.parseObject(sysNotifyService.selfList(params), PageDTO.class);
    }

    @BsCLog("我的详情界面")
    @RequiresPermissions("sys:notify:notify")
    @GetMapping(value = "/selfNotify")
    public String selfNotify() {
        return prefix + "selfNotify";
    }

    @BsCLog("我的通知列表")
    @GetMapping("/selfList")
    @ResponseBody
    public PageDTO selfList(@RequestParam Map<String, Object> params) {
        params.put("userId", getUserId());
        return JSON.parseObject(sysNotifyService.selfList(params), PageDTO.class);
    }

    @BsCLog("我的通知列表")
    @GetMapping("/selfNoReadList")
    @ResponseBody
    public PageDTO selfNoReadList(@RequestParam Map<String, Object> params) {
        params.put("userId", getUserId());
        params.put("isRead", "0");
        return JSON.parseObject(sysNotifyService.selfList(params), PageDTO.class);
    }

    @BsCLog("读取通知")
    @RequiresPermissions("sys:notify:edit")
    @GetMapping(value = "/read/{id}")
    public String read(@PathVariable("id") Long id, Model model) {
        SysNotifyDO notify = sysNotifyService.get(id);
        //更改阅读状态
        SysNotifyRecordDO sysNotifyRecordDO = new SysNotifyRecordDO();
        sysNotifyRecordDO.setNotifyId(id);
        sysNotifyRecordDO.setUserId(getUserId());
        sysNotifyRecordDO.setReadDate(new Date());
        sysNotifyRecordDO.setIsRead(Setting.SYS_NOTIFY_READ_YES);
        sysNotifyRecordService.changeRead(sysNotifyRecordDO);
        model.addAttribute("notify", notify);
        return prefix + "read";
    }
}
